﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.Mvc;
using Kooboo.Globalization;
using Kooboo.IoC;
using Kooboo.Web.Mvc;
using Kooboo.Commerce.Contexts.Countries;
using Kooboo.Commerce.Contexts.Customers;
using Kooboo.Web.Mvc.Paging;

namespace Kooboo.Web.Areas.Commerce.Controllers
{
    using Kooboo.Commerce;
    using Kooboo.Web.Areas.Commerce;
    using Kooboo.Web.Mvc;

    public class CustomerController : ManagementController
    {
        #region index
        public ActionResult Index(Int32? page)
        {
            var pageIndex = page ?? 1;
            if (pageIndex < 1)
                pageIndex = 1;

            var list = this.Actor
                .QueryCustomers()
                .OrderByDescending(i => i.Id)
                .AsEnumerable();
            var pagedList = list.ToPagedList(pageIndex, Configuration.PageSize);

            return View(pagedList);
        }


        #endregion

        #region Create
        public ActionResult Create(string redirect)
        {
            ViewData["Countries"] = this.Actor
                .QueryCountries()
                .ToSelectableList();

            SetCustomerValidator(this.Url.Action<CustomerController>(i => i.Create(null, null)));


            ViewData["DefaultPassword"] = Kooboo.Commerce.Configuration.DefaultPassword;

            return View(ObjectContainer.CreateInstance<ICustomer>());
        }

        [HttpPost]
        public ActionResult Create(ICustomer customer, string password)
        {
            if (ModelState.IsValid)
            {

                try
                {
                    this.Actor.Post(customer, password);
                }
                catch (ArgumentNullException)
                {
                    return Json(new { Message = "The user name is required.".Localize() });
                }
                catch (DuplicateNameException)
                {
                    return Json(new { Message = "The user name has been registered.".Localize() });
                }

                return Json(new { Data = customer.Id });
            }
            else
            {
                return Json(new { Message = ModelState.GetErrorMessages() });
            }


        }
        #endregion

        #region Edit

        public ActionResult Edit(int id)
        {
            SetCustomerValidator(this.Url.Action<CustomerController>(i => i.Edit(null)));
            this.SetValidators();

            this.ViewData["ReturnUrl"] = Request["ReturnUrl"];

            var customer = this.Actor
                .QueryCustomers()
                .Where(i => i.Id == id)
                .FirstOrDefault();


            ViewData["Countries"] = this.Actor.QueryCountries()
                .ToSelectableList(customer.Country);

            ViewData["address_add_action"] = this.Url.Action<CustomerController>(i => i.AddAddress(UrlParameter<int>.Empty, null));
            ViewData["address_update_action"] = this.Url.Action<CustomerController>(i => i.UpdateAddress(UrlParameter<int>.Empty, null));
            ViewData["address_delete_action"] = this.Url.Action<CustomerController>(i => i.RemoveAddress(UrlParameter<int>.Empty, null));
            ViewData["change_password_action"] = this.Url.Action<CustomerController>(i => i.ChangePassword(id, null, null));
            ViewData["order_add_action"] = this.Url.Action<OrderController>(i => i.Create(id.ToString()));


            ViewData["addresslist"] = customer.Addresses
                .Select(i => new
                    {
                        i.Id,
                        i.Address1,
                        i.Address2,
                        i.City,
                        CountryCode = i.Country.CountryCode,
                        CountryName = i.Country.CountryName,
                        i.FirstName,
                        i.LastName,
                        i.Phone,
                        i.Postcode,
                        i.State
                    })
                    .ToArray()
                    .SerializeToJson();

            ViewData["Orders"] = this.GetOrders(customer, 1).SerializeToJson();

            ViewData["PageCount"] = (int)Math.Ceiling(customer.Orders.Count() / (double)2);

            ViewData["EditMode"] = true;


            return View(customer);
        }

        void SetValidators()
        {


            ViewData["address_validator"] = ModelClientMetadataBuilder
                .BuildFor<IAddress>("", "address-form")
                .ValidateFor(i => i.Address1)
                .ValidateFor(i => i.Address2)
                .ValidateFor(i => i.City)
                .ValidateFor(i => i.FirstName)
                .ValidateFor(i => i.LastName)
                .ValidateFor(i => i.Phone)
                .ValidateFor(i => i.Postcode)
                .ToMetadata();
        }

        private void SetCustomerValidator(string action)
        {
            ViewData["customer_validator"] = ModelClientMetadataBuilder
                .BuildFor<ICustomer>(action)
                .ValidateFor(i => i.City)
                .ValidateFor(i => i.Country)
                .ValidateFor(i => i.FirstName)
                .ValidateFor(i => i.LastName)
                .ValidateFor(i => i.MailAddress)
                //.ValidateFor(i => i.MiddleName) //for task835
                .ValidateFor(i => i.Mobile)
                .ValidateFor(i => i.Telphone)
                .ValidateFor(i => i.UserName)
                .ToMetadata();
        }

        [HttpPost]
        public ActionResult Edit(ICustomer customer)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    this.Actor.Put(customer);

                }
                catch (ArgumentNullException)
                {
                    return Json(new { Message = "The user name is required.".Localize() });
                }
                catch (DuplicateNameException)
                {
                    return Json(new { Message = "The user name has been registered.".Localize() });
                }
                catch (KeyNotFoundException)
                {
                    return Json(new { Message = "The user name does not exist.".Localize() });
                }
                //new { Message = "The profile is updated.".Localize() }
                return Json(true);
            }
            else
            {
                return Json(new { Message = ModelState.GetErrorMessages() });
            }
        }
        #endregion

        #region Order
        public ActionResult Orders(ICustomer customer, int pageIndex)
        {
            return Json(this.GetOrders(customer, pageIndex), JsonRequestBehavior.AllowGet);
        }
        CustomerOrderViewModel[] GetOrders(ICustomer customer, int pageIndex)
        {
            String currentUrl = Request.Url.ToString();

            return customer
                .Orders
                .Skip((pageIndex - 1) * 2)
                .Take(2)
                .Select(i => new CustomerOrderViewModel
                {
                    Id = i.Id,
                    Quantity = i.OrderItems.Count,
                    Total = i.Total,
                    OrderDate = i.OrderDate.ToString(),
                    OrderStatus = Enum.GetName(typeof(OrderStatus), i.OrderStatus),
                    DetailUrl = this.Url.Action("Detail", "Order", new { id = i.Id, returnUrl = currentUrl })
                })
                .ToArray();

        }
        #endregion

        #region Password
        [HttpPost]
        public ActionResult ChangePassword(int id, string newPassword, string reNewPassword)
        {
            if (String.IsNullOrEmpty(newPassword))
            {
                return Json(new { Message = "Please enter a new password.".Localize() });
            }

            if (newPassword != reNewPassword)
            {
                return Json(new { Message = "The two passwords do not match.".Localize() });
            }

            var userName = this.Actor
                .QueryCustomers()
                .Where(i => i.Id == id)
                .Select(i => i.UserName)
                .FirstOrDefault();


            if (Kooboo.Connect.UserServices.ChangePassword(userName, newPassword))
            {
                return Json(new { Message = "The password is changed.".Localize() });
            }
            else
            {
                return Json(new { Message = "The old password is incorrect.".Localize() });
            }
        }
        #endregion

        #region Addresses
        public ActionResult Addresses(ICustomer customer)
        {
            return View(customer.Addresses);
        }

        [HttpPost]
        public ActionResult AddAddress(int customerId, IAddress address)
        {
            if (ModelState.IsValid)
            {
                var customer = ObjectContainer.CreateInstance<ICustomer>();
                customer.Id = customerId;

                this.Actor.Post(customer, address);

                return Json(new { Data = address.Id });
            }
            else
            {
                return Json(new { Message = ModelState.GetErrorMessages() });
            }


        }

        [HttpPost]
        public ActionResult UpdateAddress(int customerId, IAddress address)
        {
            if (ModelState.IsValid)
            {

                var customer = ObjectContainer.CreateInstance<ICustomer>();
                customer.Id = customerId;

                this.Actor.Put(customer, address);

                return Json(new { Data = address.Id });
            }
            else
            {
                return Json(new { Message = ModelState.GetErrorMessages() });
            }
        }

        [HttpPost]
        public ActionResult RemoveAddress(int customerId, IAddress address)
        {

            var customer = ObjectContainer.CreateInstance<ICustomer>();
            customer.Id = customerId;

            this.Actor.Delete(customer, address);

            return Json(true);
        }
        #endregion
    }

    public class CustomerOrderViewModel
    {
        public int Id
        {
            get;
            set;
        }

        public int Quantity
        {
            get;
            set;
        }

        public decimal Total
        {
            get;
            set;
        }

        public string OrderDate
        {
            get;
            set;
        }

        public string OrderStatus
        {
            get;
            set;
        }

        public String DetailUrl { get; set; }
    }
}
